package zzu.xjc.http;

import zzu.xjc.http.util.LRUCache;
import zzu.xjc.http.util.Logger;

import java.nio.ByteBuffer;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;

public class FilesLRUCache implements FilesCache {
    private final LRUCache<String,List<ByteBuffer>> cache;
    private final ReentrantLock lock = new ReentrantLock();
    private final BufferPool bufferPool;

    @Override
    public List<ByteBuffer> get(String url) {
        List<ByteBuffer> originList = cache.get(url);
        if (originList == null){
            return null;
        }
        List<ByteBuffer> resultList = new LinkedList<>();
        for (ByteBuffer originBuffer : originList) {
            resultList.add( bufferPool.allocate().put(originBuffer).flip() );
        }
        originList.forEach(ByteBuffer::rewind);
        return resultList;
    }

    @Override
    public void put(String url, List<ByteBuffer> bufferList) {
        LinkedList<ByteBuffer> cacheList = bufferPool.allocate(bufferList.size());
        Iterator<ByteBuffer> iter = cacheList.iterator();
        for (ByteBuffer originBuf : bufferList) {
            ByteBuffer buffer = iter.next();
            buffer.put(originBuf);
        }
        bufferList.forEach(ByteBuffer::rewind);
        cacheList.forEach(ByteBuffer::flip);
        lock.lock();
        try {
            cache.put(url, cacheList);
        }finally {
            lock.unlock();
        }
    }

    @Override
    public boolean contains(String url) {
        return cache.containsKey(url);
    }

    @Override
    public boolean contains(List<ByteBuffer> list) {
        return cache.containsValue(list);
    }

    FilesLRUCache(int size , BufferPool bufferPool){
        this.bufferPool = bufferPool;
        this.cache = new LRUCache<>(size,
                url -> Logger.info("File out of LUR Cache, Url :" + url),
                bufferPool::giveback);
    }
}
